package com.rabbit.icore;

import com.rabbitmq.client.ShutdownSignalException;
import lombok.Data;
import org.springframework.amqp.AmqpIOException;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 包装了交换机和队列的创建、绑定、获取
 * 业务人员使用时只需要指定交换机的个数就可以了，交换机的名称、类型由具体业务在initExchange中定型
 */
@Data
@Component
public class Exchanges {
    @Autowired
    private RabbitAdmin rabbitAdmin;
    //由业务人员配置
    @Value("${spring.rabbitmq.exchange-number:5}")//不设置默认值会报错，测试一下，默认值是5
    private int exchangeNumber;
    static List<String> exchanges;
    private int count;


    //初始化交换机集合
    public Exchanges() {
        exchanges = new ArrayList<>();
    }

    /**
     * 轮询的方式获取交换机，自己可以扩展随机、繁忙等
     * @return
     */
    public String getExchange() {
        String exchange = exchanges.get(count % exchangeNumber);
        if (count >= exchangeNumber) {
            count = count - exchangeNumber;
        }
        count++;
        return exchange;
    }

    /**
     * 根据指定的个数创建交换机，名字可根据项目名来固定，同样可以在配置文件里配置。
     */
    public void initExchange() {
        if (exchanges.size() < exchangeNumber) {
            for (int i = 0; i < exchangeNumber; i++) {
                String exchangeName = "prefboss" + i;
                if (!exchanges.contains(exchangeName)) {
                    exchanges.add(exchangeName);
                }
            }
        }
        for (String exchangeName : exchanges) {
            rabbitAdmin.declareExchange(new DirectExchange(exchangeName));
        }
    }


    /**
     * 创建队列并绑定交换机
     * @param queue 队列名
     * @param routingKey 路由键
     */
    public void createExchangeQueueAndBinding(String queue, String routingKey) {
        //声明交换机
        initExchange();
        //根据appId和tenantId声明队列,不同的appId和tenantId对应不同的队列
        rabbitAdmin.declareQueue(new Queue(queue));
        //绑定交换机和队列
        for (String exchange : exchanges) {
            try {
                rabbitAdmin.declareBinding(new Binding(queue, Binding.DestinationType.QUEUE, exchange, routingKey, null));
            } catch (Exception e) {
                if (e instanceof AmqpIOException || e instanceof ShutdownSignalException || e instanceof IOException) {
                    try {
                        rabbitAdmin.declareExchange(new DirectExchange(exchange));
                        rabbitAdmin.declareBinding(new Binding(queue, Binding.DestinationType.QUEUE, exchange, routingKey, null));
                    } catch (Exception exception) {
                        System.out.println("绑定异常，记录日志，原因：" + Arrays.toString(e.getStackTrace()));
                    }
                } else {
                    System.out.println("绑定异常，记录日志，原因：" + Arrays.toString(e.getStackTrace()));
                }
            }
        }
    }
}

